#include "Alice/Core/QuadTree.h"
#include "Alice/Log/Log.h"
#include "Alice/Core/World.h"
#include "Alice/Components/TransformComp.hpp"

namespace Alice
{

void QuadTree::__Destroy(QuadTreeNode* node)
{
    if (node == nullptr)
    {
        return ;
    }
    else
    {
        __Destroy(node->left_top);
        __Destroy(node->left_bottom);
        __Destroy(node->right_top);
        __Destroy(node->right_bottom);
        delete node;
    }
}

int QuadTree::__Quadrant(QuadTreeNode* node, float x, float y)
{
    int quadrant = 1;

    float left = node->rect.left;
    float top = node->rect.top;
    float right = node->rect.right;
    float bottom = node->rect.bottom;

    if (x >= left + (right - left) / 2 && y <= top + (bottom - top) / 2)
        quadrant = 1;
    else if (x <= left + (right - left) / 2 && y <= top + (bottom - top) / 2)
        quadrant = 2;
    else if (x <= left + (right - left) / 2 && y >= top + (bottom - top) / 2)
        quadrant = 3;
    else if (x >= left + (right - left) / 2 && y >= top + (bottom - top) / 2)
        quadrant = 4;

    return quadrant;
}

void QuadTree::__Division(QuadTreeNode* node)
{
    if (node->is_leaf)
    {
        float left = node->rect.left;
        float top = node->rect.top;
        float right = node->rect.right;
        float bottom = node->rect.bottom;

        node->left_top = new QuadTreeNode(
            left,
            top, 
            left + (right - left) / 2,
            top + (bottom - top) / 2
        );
        node->left_bottom = new QuadTreeNode(
            left,
            top + (bottom - top) / 2,
            left + (right - left) / 2,
            bottom
        );
        node->right_top = new QuadTreeNode(
            left + (right - left) / 2,
            top,
            right,
            top + (bottom - top) / 2
        );
        node->right_bottom = new QuadTreeNode(
            left + (right - left) / 2,
            top + (bottom - top) / 2,
            right,
            bottom
        );
        
        node->is_leaf = false;
    }
}

void QuadTree::__Insert(QuadTreeNode* node, Entity entity)
{
    if (node->entitys.size() < m_capacity)
    {
        node->entitys.insert(entity);
    }

    __Division(node);

    TransformComp& tf_comp = m_world->GetComp<TransformComp>(entity);
    int quadrant = __Quadrant(
        node,
        tf_comp.position.x,
        tf_comp.position.y
    );

    if (quadrant == 1)
        __Insert(node->right_top, entity);
    else if (quadrant == 2)
        __Insert(node->left_top, entity);
    else if (quadrant == 3)
        __Insert(node->left_bottom, entity);
    else if (quadrant == 4)
        __Insert(node->right_bottom, entity);
}

bool QuadTree::__Check(QuadTreeNode* node, Entity entity)
{
    TransformComp& temp_tf = m_world->GetComp<TransformComp>(entity);

    if (temp_tf.position.x < node->rect.left ||
        temp_tf.position.x > node->rect.right ||
        temp_tf.position.y < node->rect.top ||
        temp_tf.position.y > node->rect.bottom)
    {
        return false;
    }

    return true;
}

std::set<Entity>& QuadTree::__FindNeighbor(QuadTreeNode* node, Entity entity)
{
    if (node->is_leaf || node->entitys.find(entity) != node->entitys.end())
    {
        // 检查并更新最终查找到的区域
        std::set<Entity>::iterator iter = node->entitys.begin();
        while (iter != node->entitys.end())
        {
            if (__Check(node, *iter) == false)
                node->entitys.erase(iter++);
            else 
                iter++;
        }

        return node->entitys;
    }

    TransformComp& tf_comp = m_world->GetComp<TransformComp>(entity);

    int quadrant = __Quadrant(
        node,
        tf_comp.position.x,
        tf_comp.position.y
    );

    if (quadrant == 1)
        __FindNeighbor(node->right_top, entity);
    else if (quadrant == 2)
        __FindNeighbor(node->left_top, entity);
    else if (quadrant == 3)
        __FindNeighbor(node->left_bottom, entity);
    else if (quadrant == 4)
        __FindNeighbor(node->right_bottom, entity);

    // 这是一个递归函数，这个 return 永远也不会被执行
    // 这个 return 仅用来取消编译器的警告
    
    return node->entitys;
}

void QuadTree::Create(float left, float top, float right, float bottom)
{
    // 新的树被创建前释放旧的树
    __Destroy(m_root);
    
    m_root = new QuadTreeNode(left, top, right, bottom);
    
    ALICE_INFO("Successfully create QuadTree: Rect - [ {}, {}, {}, {} ]",
        left, top, right, bottom
    );
}

void QuadTree::Insert(Entity entity)
{
    __Insert(m_root, entity);
}

std::set<Entity>& QuadTree::FindNeighbor(Entity entity)
{
    return __FindNeighbor(m_root, entity);
}

} // namespace Alice
